﻿namespace LogManager.Console
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    public class ConsoleSpinner
    {
        private int _currentAnimationFrame;
        public bool IsRunning { get; private set; }
        public Task SpinTask { get; private set; }
        public ConsoleSpinner()
        {
            SpinnerAnimationFrames = new[]
                                     {
                                         "|",
                                         "/",
                                         "-",
                                         "\\"
                                     };
        }

        public string[] SpinnerAnimationFrames { get; set; }

        public void Spin()
        {
            // Store the current position of the cursor
            var originalX = Console.CursorLeft;
            var originalY = Console.CursorTop;

            // Write the next frame (character) in the spinner animation
            Console.Write("\r  " + SpinnerAnimationFrames[_currentAnimationFrame] + "  ");

            // Keep looping around all the animation frames
            _currentAnimationFrame++;
            if (_currentAnimationFrame == SpinnerAnimationFrames.Length)
            {
                _currentAnimationFrame = 0;
            }

            // Restore cursor to original position
            Console.SetCursorPosition(originalX, originalY);
        }

        public void Start()
        {
            Console.CursorVisible = false;
            this.IsRunning = true;
            this.SpinTask = CreateSpinningTask();
            this.SpinTask.Start();
        }

        public void Stop()
        {
            this.IsRunning = false;
            while (!this.SpinTask.IsCompleted)
            {
                Thread.Sleep(10);
            }
            Console.Write("\r             ");
            Console.CursorVisible = true;
        }

        private Task CreateSpinningTask()
        {
            return new Task(() =>
            {
                while (this.IsRunning)
                {
                    Thread.Sleep(100);
                    this.Spin();
                }

            });
        }
    }
}
